/* eslint-disable no-param-reassign */
import {
  filterValueRules,
  FormNotifyState,
  generateRules,
  getEditorProvider,
  IEditorContainerController,
  IEditorController,
  IEditorProvider,
  IFormDetailContainerController,
  Srfuf,
} from '@ibiz-template/runtime';
import { IDEFormItem, IValueItemEditor } from '@ibiz/model-core';
import Schema from 'async-validator';
import { dayjs } from 'element-plus';
import { createUUID, isNilOrEmpty } from 'qx-util';
import { ModelError, RuntimeError } from '@ibiz-template/core';
import { EditFormController } from '../../edit-form';
import { FormController } from '../../form/form.controller';
import { FormDetailController } from '../form-detail/form-detail.controller';
import { FormItemState } from './form-item.state';

export class FormItemController
  extends FormDetailController<IDEFormItem>
  implements IEditorContainerController
{
  declare state: FormItemState;

  protected createState(): FormItemState {
    return new FormItemState(this.parent?.state);
  }

  /**
   * 上下文
   *
   * @author lxm
   * @date 2022-08-24 20:08:55
   * @type {IContext}
   */
  readonly context: IContext;

  /**
   * 视图参数
   *
   * @author lxm
   * @date 2022-08-24 20:08:52
   * @type {IParams}
   */
  readonly params: IParams;

  /**
   * 编辑器控制器
   *
   * @author lxm
   * @date 2022-08-24 20:08:42
   * @type {IEditorController}
   */
  editor?: IEditorController;

  /**
   * 编辑器适配器
   *
   * @author lxm
   * @date 2022-08-24 20:08:42
   */
  editorProvider?: IEditorProvider;

  /**
   * 表单项校验器实例
   *
   * @author lxm
   * @date 2022-09-04 18:09:56
   * @private
   * @type {Schema}
   */
  private validator!: Schema;

  /**
   * 值规则
   *
   * @author lxm
   * @date 2022-09-01 22:09:49
   * @type {IData}
   */
  rules: IData = [];

  /**
   * 表单项名称
   *
   * @author lxm
   * @date 2022-09-04 18:09:32
   * @readonly
   */
  get name(): string {
    return this.model.fieldName || this.model.id!;
  }

  /**
   * 表单项对应属性的值
   *
   * @author lxm
   * @date 2022-08-24 22:08:25
   * @readonly
   * @type {unknown}
   */
  get value(): unknown {
    return this.form.data[this.name];
  }

  /**
   * 值项
   * @author lxm
   * @date 2023-05-31 02:31:27
   * @readonly
   * @type {(string | undefined)}
   */
  get valueItemName(): string | undefined {
    if (this.model.editor) {
      return (this.model.editor as IValueItemEditor).valueItemName;
    }
    return undefined;
  }

  /**
   * Creates an instance of FormItemController.
   *
   * @author chitanda
   * @date 2023-06-14 10:06:23
   * @param {IDEFormItem} model 表单模型
   * @param {FormController} form 表单控制器
   * @param {IFormDetailContainerController} [parent] 父容器控制器
   */
  constructor(
    model: IDEFormItem,
    form: FormController,
    parent?: IFormDetailContainerController,
  ) {
    super(model, form, parent);
    this.context = form.context;
    this.params = form.params;
  }

  /**
   * 单位
   * @author lxm
   * @date 2023-05-24 05:46:52
   * @readonly
   * @type {(string | undefined)}
   */
  get unitName(): string | undefined {
    return this.model.unitName;
  }

  /**
   * 值格式化
   * @author lxm
   * @date 2023-05-24 05:46:56
   * @readonly
   * @type {(string | undefined)}
   */
  get valueFormat(): string | undefined {
    return this.model.valueFormat;
  }

  /**
   * 初始化
   *
   * @author lxm
   * @date 2022-08-24 20:08:42
   * @protected
   * @returns {*}  {Promise<void>}
   */
  protected async onInit(): Promise<void> {
    await super.onInit();
    // 空输入默认值
    this.state.required = !this.model.allowEmpty;
    // 初始化编辑器控制器,除了隐藏都会需要适配器
    if (this.model.editor && this.model.editor.editorType !== 'HIDDEN') {
      this.editorProvider = await getEditorProvider(this.model.editor);
      if (this.editorProvider) {
        this.editor = await this.editorProvider.createController(
          this.model.editor,
          this,
        );
        await this.initRules();
      }
    }
  }

  /**
   * 初始化值规则
   *
   * @author lxm
   * @date 2022-09-02 09:09:27
   * @protected
   * @returns {*}
   */
  protected async initRules(): Promise<void> {
    const formItemsVRs = filterValueRules(
      this.form.model.deformItemVRs || [],
      this.name,
    );
    if (!formItemsVRs) {
      return;
    }
    this.rules = generateRules(formItemsVRs, this.name, this.valueItemName);
    // 初始化async-validator实例
    this.validator = new Schema({ [this.name]: this.rules });
  }

  /**
   * 计算启用条件的禁用
   *
   * @author lxm
   * @date 2022-09-20 00:09:57
   * @param {(string | FormNotifyState)} name
   * @returns {*}
   */
  calcEnableCond(): void {
    const { enableCond } = this.model;
    const isNew = this.data.srfuf === Srfuf.CREATE;
    if (!enableCond) {
      // enableCond为0省略为不存在了
      this.state.enableCondDisabled = true;
    } else if ((isNew && enableCond === 2) || (!isNew && enableCond === 1)) {
      this.state.enableCondDisabled = true;
    }
  }

  async dataChangeNotify(name: string[]): Promise<void> {
    await super.dataChangeNotify(name);
    const { resetItemNames } = this.model;

    // 重置项，变更时自己的值置空
    let isReset = false;
    if (resetItemNames && resetItemNames.length > 0) {
      resetItemNames.forEach((resetItemName: string) => {
        if (name.includes(resetItemName)) {
          isReset = true;
        }
      });
    }
    if (isReset) {
      this.setDataValue(null, this.name);
    }

    // 刚加载初始化时的值不校验,只校验值项和自身值变更
    if (name.includes(this.name) || name.includes(this.valueItemName!)) {
      this.validate();
    }

    // 有表单项更新，且是自身变更时，触发表单项更新
    if (name.includes(this.name) && this.model.deformItemUpdateId) {
      await (this.form as EditFormController).updateFormItem(
        this.model.deformItemUpdateId,
      );
    }
  }

  async formStateNotify(state: FormNotifyState): Promise<void> {
    super.formStateNotify(state);

    // 计算启用条件
    this.calcEnableCond();

    // 触发默认值
    if (state === FormNotifyState.LOAD) {
      this.setDefaultValue(false);
    }
  }

  protected calcDynamicLogic(names: string[], state?: FormNotifyState): void {
    // 隐藏表单项不计算动态逻辑
    if (!this.model.hidden) {
      super.calcDynamicLogic(names, state);
    }
  }

  /**
   * 表单项值规则校验
   * 如果表单项不显示则不校验直接返回true
   *
   * @author lxm
   * @date 2022-09-01 22:09:29
   */
  async validate(): Promise<boolean> {
    if (!this.state.visible) {
      this.state.error = null;
      return true;
    }

    // 必填校验
    if (this.state.required && isNilOrEmpty(this.data[this.name])) {
      this.state.error = `请填写${this.model.caption || ''}`;
      return false;
    }

    if (this.validator) {
      try {
        await this.validator.validate(this.data);
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
      } catch ({ errors, _fields }: any) {
        this.state.error = (errors as IData[])[0].message;
        return false;
      }
    }
    this.state.error = null;
    return true;
  }

  /**
   * 设置表单数据的值
   *
   * @author lxm
   * @date 2022-08-24 10:08:40
   * @param {unknown} value 要设置的值
   * @param {string} name 要设置的表单数据的属性名称
   */
  async setDataValue(value: unknown, name?: string): Promise<void> {
    name = name || this.name;
    await this.form.setDataValue(name, value);
  }

  /**
   * 设置默认值
   *
   * @author lxm
   * @date 2022-09-15 22:09:52
   * @param {boolean} isCreate 新建默认值还是更新默认值
   */
  setDefaultValue(isCreate: boolean, data: IData = this.data): void {
    const { createDVT, createDV, updateDVT, updateDV } = this.model;
    const valueType = isCreate ? createDVT : updateDVT;
    const defaultValue = isCreate ? createDV : updateDV;
    // 置空
    if (valueType === 'RESET') {
      data[this.name] = null;
      return;
    }

    // 除置空之外的默认值类型，有值的时候不走
    if (this.value) {
      return;
    }
    // 没有配置默认值
    if (isNilOrEmpty(valueType) && isNilOrEmpty(defaultValue)) {
      return;
    }
    // 没有配类型，配了默认值的直接赋值默认值
    if (!valueType && defaultValue) {
      data[this.name] = defaultValue;
      return;
    }
    switch (valueType) {
      // 当前应用数据，优先取视图参数，视图参数没有取上下文
      case 'APPDATA':
        if (Object.prototype.hasOwnProperty.call(this.params, defaultValue!)) {
          data[this.name] = this.params[defaultValue!];
        }
        if (Object.prototype.hasOwnProperty.call(this.context, defaultValue!)) {
          data[this.name] = this.context[defaultValue!];
        }
        break;
      // 当前操作用户(名称)
      case 'OPERATORNAME':
        data[this.name] = this.context.srfusername;
        break;
      // 当前操作用户(编号)
      case 'OPERATOR':
        data[this.name] = this.context.srfuserid;
        break;
      // 当前时间
      case 'CURTIME':
        data[this.name] = dayjs().format(this.model.valueFormat);
        break;
      // 数据对象属性
      case 'PARAM':
        data[this.name] = this.data[defaultValue!];
        break;
      case 'SESSION': // 用户全局对象
      case 'APPLICATION': // 系统数据对象
        // 取appData里的上下文
        if (!ibiz.appData?.context) {
          throw new RuntimeError('appdata.context不存在');
        }
        data[this.name] = ibiz.appData.context[defaultValue!];
        break;
      // 网页请求用视图参数
      case 'CONTEXT':
        data[this.name] = this.params[defaultValue!];
        break;
      // 唯一编码
      case 'UNIQUEID':
        data[this.name] = createUUID();
        break;
      default:
        // 未支持类型： SESSION：用户全局对象、 APPLICATION：系统全局对象、 CONTEXT：网页请求。这些应该是后台的模式，前台暂不处理
        throw new ModelError(this.model, `默认值类型[${valueType}]未支持`);
    }
  }
}
